export enum ExecutionMode {
  ACTIVE = 0,        // 主动执行模式
  SEMI_PASSIVE = 1,  // 半被动模式(需要确认)
  PASSIVE = 2,       // 完全被动模式(队列执行)
  AUTOMATIC = 3,     // 自动判断执行模式
  TRIGGERED = 4,     // 条件触发模式
  INTELLIGENT = 5    // 智能模式(自动学习)
}

export interface ExecutionOptions {
  force?: boolean;
  exePath?: string;
  args?: string[];
  redis?: {
    host?: string;
    port?: number;
    password?: string;
    db?: number;
    fallbackToLocal?: boolean; // 连接失败时回退到本地存储
  };
  mode?: ExecutionMode; // 执行模式
  confirmMessage?: string; // 确认提示消息
  triggerCondition?: () => boolean; // 触发条件函数
}

export class ExecutionEngine {
  private mode: ExecutionMode = ExecutionMode.ACTIVE;
  private queue: Array<() => Promise<void>> = [];
  private confirmMessage = 'Confirm?';
  private confirmCallback: (message: string) => Promise<boolean> = () => Promise.resolve(true);

  getMode(): ExecutionMode {
    return this.mode;
  }

  setMode(mode: ExecutionMode): this {
    this.mode = mode;
    return this;
  }

  setConfirmCallback(callback: (message: string) => Promise<boolean>): this {
    this.confirmCallback = callback;
    return this;
  }

  setConfirmMessage(message: string): this {
    this.confirmMessage = message;
    return this;
  }

  flushQueue(): void {
    const tasks = [...this.queue];
    this.queue = [];
    tasks.forEach(task => task());
  }

  private redisClient: any = null;

  private async initRedis(options: ExecutionOptions['redis']) {
    if (!options || this.redisClient) return;
    
    try {
      const { createClient } = await import('redis');
      this.redisClient = createClient({
        socket: {
          host: options.host || '127.0.0.1',
          port: options.port || 6379,
        },
        password: options.password,
        database: options.db || 0
      });
      
      await this.redisClient.connect();
      this.redisClient.on('error', (err: Error) => {
        console.warn('Redis error:', err.message);
        if (options.fallbackToLocal) {
          this.redisClient = null;
        }
      });
    } catch (err) {
      console.warn('Redis init failed:', err instanceof Error ? err.message : String(err));
      if (options.fallbackToLocal) {
        this.redisClient = null;
      } else {
        throw err;
      }
    }
  }

  private async executeExe(options: ExecutionOptions): Promise<void> {
    const { exePath, args = [], redis } = options;
    
    if (redis) {
      await this.initRedis(redis);
      if (this.redisClient) {
        // Redis执行逻辑
        const key = `exec:${Date.now()}`;
        await this.redisClient.set(key, JSON.stringify({ exePath, args }));
        return;
      }
    }

    if (!exePath) throw new Error('EXE path required');
    
    const { exec } = await import('child_process');
    return new Promise((resolve, reject) => {
      exec(`"${exePath}" ${args.join(' ')}`, (error, stdout, stderr) => {
        if (error) return reject(error);
        if (stderr) console.warn(stderr);
        resolve();
      });
    });
  }

  async execute(
    fn: () => void | Promise<void>,
    options: ExecutionOptions = {}
  ): Promise<void> {
    if (options.exePath) {
      return this.executeExe(options);
    }

    if (options.force) {
      await fn();
      return;
    }

    switch (this.mode) {
      case ExecutionMode.ACTIVE:
        await fn();
        break;
      
      case ExecutionMode.SEMI_PASSIVE:
        const confirmed = await this.confirmCallback(this.confirmMessage);
        if (confirmed) {
          await fn();
        }
        break;
      
      case ExecutionMode.PASSIVE:
        this.queue.push(async () => {
          try {
            await fn();
          } catch (err) {
            console.error('Queued execution failed:', err);
          }
        });
        break;
    }
  }
}